home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / GAMES / C059B.ZIP / SRC3.ZIP / MUSIC.C < prev   
C/C++ Source or Header  |  1990-07-18  |  12KB  |  456 lines

  1. /*    SCCS Id: @(#)music.c    3.0    88/10/22
  2. /*     Copyright (c) 1989 by Jean-Christophe Collet */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * This file contains the different functions designed to manipulate the
  7.  * musical instruments and their various effects.
  8.  *
  9.  * Actually the list of instruments / effects is :
  10.  *
  11.  * Flute        may calm snakes if player has enough dexterity
  12.  * Magic flute        may put monsters to sleep:  area of effect depends
  13.  *            on player level.
  14.  * Horn            Will awaken monsters:  area of effect depends on player
  15.  *            level.  May also scare monsters.
  16.  * Fire horn        Acts like a wand of fire.
  17.  * Frost horn        Acts like a wand of cold.
  18.  * Bugle        Will awaken soldiers (if any):  area of effect depends
  19.  *            on player level.
  20.  * Harp            May calm nymph if player has enough dexterity.
  21.  * Magic harp        Charm monsters:  area of effect depends on player
  22.  *            level.
  23.  * Drum            Will awaken monsters like the horn.
  24.  * Drum of earthquake    Will initiate an earthquake whose intensity depends
  25.  *            on player level.  That is, it creates ramdom pits
  26.  *            called here chasms.
  27.  */
  28.  
  29.  
  30. #include "hack.h"
  31.  
  32. #ifdef MUSIC
  33. #include <ctype.h>
  34.  
  35. static void FDECL(awaken_monsters,(int));
  36. static void FDECL(put_monsters_to_sleep,(int));
  37. static void FDECL(charm_snakes,(int));
  38. static void FDECL(calm_nymphs,(int));
  39. static void NDECL(awaken_soldiers);
  40. static void FDECL(charm_monsters,(int));
  41. static void FDECL(do_earthquake,(int));
  42. static int FDECL(do_improvisation,(struct obj *));
  43.  
  44. /*
  45.  * Wake every monster in range...
  46.  */
  47.  
  48. static void
  49. awaken_monsters(distance)
  50. int distance;
  51. {
  52.     register struct monst *mtmp = fmon;
  53.  
  54.     while(mtmp) {
  55.         if (dist(mtmp->mx, mtmp->my) < distance/3) {
  56.             /* May scare some monsters */
  57.             if (!resist(mtmp, SCROLL_SYM, 0, NOTELL))
  58.               mtmp->mflee = 1;
  59.         } else if (dist(mtmp->mx, mtmp->my) < distance) {
  60.             mtmp->msleep = 0;
  61.             mtmp->mcanmove = 1;
  62.             mtmp->mfrozen = 0;
  63.         }
  64.         mtmp = mtmp->nmon;
  65.     }
  66. }
  67.  
  68. /*
  69.  * Make monsters fall asleep.  Note that they may resist the spell.
  70.  */
  71.  
  72. static void
  73. put_monsters_to_sleep(distance)
  74. int distance;
  75. {
  76.     register struct monst *mtmp = fmon;
  77.  
  78.     while(mtmp) {
  79.           if (dist(mtmp->mx, mtmp->my) < distance)
  80.             if(mtmp->mcanmove && !resist(mtmp, WAND_SYM, 0, NOTELL))
  81.               mtmp->mcanmove = mtmp->mfrozen = 0;
  82.         mtmp = mtmp->nmon;
  83.     }
  84. }
  85.  
  86. /*
  87.  * Charm snakes in range.  Note that the snakes are NOT tamed.
  88.  */
  89.  
  90. static void
  91. charm_snakes(distance)
  92. int distance;
  93. {
  94.     register struct monst *mtmp = fmon;
  95.  
  96.     while (mtmp) {
  97.         if (mtmp->data->mlet == S_SNAKE && dist(mtmp->mx, mtmp->my) < distance) {
  98.             mtmp->mpeaceful = 1;
  99.             if (cansee(mtmp->mx, mtmp->my))
  100.               pline("%s freezes and sways with the music, then seems quieter.",defmonnam(mtmp));
  101.         }
  102.         mtmp = mtmp->nmon;
  103.     }
  104. }
  105.  
  106. /*
  107.  * Calm nymphs in range.
  108.  */
  109.  
  110. static void
  111. calm_nymphs(distance)
  112. int distance;
  113. {
  114.     register struct monst *mtmp = fmon;
  115.  
  116.     while (mtmp) {
  117.         if (mtmp->data->mlet == S_NYMPH && dist(mtmp->mx, mtmp->my) < distance) {
  118.             mtmp->mpeaceful = 1;
  119.             if (cansee(mtmp->mx, mtmp->my))
  120.               pline("%s listens cheerfully to the music, then seems quieter.",defmonnam(mtmp));
  121.         }
  122.         mtmp = mtmp->nmon;
  123.     }
  124. }
  125.  
  126. /* Awake only soldiers of the level. */
  127.  
  128. static void
  129. awaken_soldiers() {
  130. #ifdef ARMY
  131. #define IS_SOLDIER(dat)    ((int)((dat) - mons) >= PM_UNARMORED_SOLDIER && \
  132.              (int) ((dat) - mons) <= PM_CAPTAIN)
  133.     register struct monst *mtmp = fmon;
  134.  
  135.     while(mtmp) {
  136.         if (IS_SOLDIER(mtmp->data)) {
  137.             mtmp->mpeaceful = mtmp->msleep = 0;
  138.             mtmp->mcanmove = 1;
  139.         }
  140.         mtmp = mtmp->nmon;
  141.     }
  142. #endif /* ARMY /**/
  143. }
  144.  
  145. /* Charm monsters in range.  Note that they may resist the spell. */
  146.  
  147. static void
  148. charm_monsters(distance)
  149. int distance;
  150. {
  151.     register struct monst *mtmp = fmon, *mtmp2;
  152.  
  153.     while(mtmp) {
  154.         mtmp2 = mtmp->nmon;
  155.         if(dist(mtmp->mx, mtmp->my) <= distance)
  156.             if(!resist(mtmp, SCROLL_SYM, 0, NOTELL))
  157.             (void) tamedog(mtmp, (struct obj *) 0);
  158.         mtmp = mtmp2;
  159.     }
  160.  
  161. }
  162.  
  163. /* Generate earthquake :-) of desired force.
  164.  * That is:  create random chasms (pits).
  165.  */
  166.  
  167. static void
  168. do_earthquake(force)
  169. int force;
  170. {
  171.     register int x,y;
  172.     struct monst *mtmp;
  173.     struct trap *chasm;
  174.     int start_x, start_y, end_x, end_y;
  175.  
  176.     start_x = u.ux - (force * 2);
  177.     start_y = u.uy - (force * 2);
  178.     end_x = u.ux + (force * 2);
  179.     end_y = u.uy + (force * 2);
  180.     if (start_x < 1) start_x = 1;
  181.     if (start_y < 1) start_y = 1;
  182.     if (end_x >= COLNO) end_x = COLNO - 1;
  183.     if (end_y >= ROWNO) end_y = ROWNO - 1;
  184.     for (x=start_x; x<=end_x; x++)
  185.       for (y=start_y; y<=end_y; y++)
  186.         if (!rn2(14 - force)) {
  187.             switch (levl[x][y].typ) {
  188. #ifdef FOUNTAINS
  189.               case FOUNTAIN : /* Make the fountain disappear */
  190.                 if (cansee(x,y))
  191.                   pline("The fountain falls into a chasm.");
  192.                 goto do_pit;
  193. #endif
  194. #ifdef SINKS
  195.               case SINK :
  196.                 if (cansee(x,y))
  197.                   pline("The kitchen sink falls into a chasm.");
  198.                 goto do_pit;
  199. #endif
  200. #ifdef ALTARS
  201.               case ALTAR :
  202.                 if (cansee(x,y))
  203.                   pline("The altar falls into a chasm.");
  204.                 goto do_pit;
  205. #endif
  206. #ifdef THRONES
  207.               case THRONE :
  208.                 if (cansee(x,y))
  209.                   pline("The throne falls into a chasm.");
  210.                 /* Falls into next case */
  211. #endif
  212.               case ROOM :
  213.               case CORR : /* Make a pit */
  214. do_pit:                chasm = maketrap(x,y,PIT);
  215.                 chasm->tseen = 1;
  216.  
  217.                 levl[x][y].doormask = 0;
  218.  
  219.                 /* We have to check whether monsters or player
  220.                    fall in a chasm... */
  221.  
  222.                 if (MON_AT(x, y)) {
  223.                 mtmp = m_at(x,y);
  224.                 if(!is_flyer(mtmp->data)) {
  225.                     mtmp->mtrapped = 1;
  226.                     if(cansee(x,y))
  227.                     pline("%s falls into a chasm!",
  228.                         Monnam(mtmp));
  229.                     else if (flags.soundok && humanoid(mtmp->data))
  230.                     You("hear a scream!");
  231.                     if ((mtmp->mhp -= rnd(6)) <= 0) {
  232.                     if(!cansee(x,y))
  233.                         pline("It is destroyed!");
  234.                     else {
  235.                         You("destroy %s!",
  236.                         mtmp->mtame ?
  237.                         a2_monnam(mtmp, "poor") :
  238.                         mon_nam(mtmp));
  239.                     }
  240.                     xkilled(mtmp,0);
  241.                     }
  242.                 }
  243.                 } else if (x == u.ux && y == u.uy) {
  244.                     if (Levitation
  245. #ifdef POLYSELF
  246.                     || is_flyer(uasmon)
  247. #endif
  248.                     ) {
  249.                         pline("A chasm opens up under you!");
  250.                         You("don't fall in!");
  251.                     } else {
  252.                         You("fall into a chasm!");
  253.                         u.utrap = rn1(6,2);
  254.                         u.utraptype = TT_PIT;
  255.                         losehp(rnd(6),"fell into a chasm",
  256.                         NO_KILLER_PREFIX);
  257.                         selftouch("Falling, you");
  258.                     }
  259.                 } else
  260.                 newsym(x,y);
  261.                 break;
  262.               case DOOR : /* Make the door collapse */
  263.                 if (levl[x][y].doormask == D_NODOOR) break;
  264.                 if (cansee(x,y))
  265.                 pline("The door collapses.");
  266.                 levl[x][y].doormask = D_NODOOR;
  267.                 mnewsym(x,y);
  268.                 if (!MON_AT(x, y) && !(x == u.ux && y == u.uy))
  269.                 newsym(x,y);
  270.                 if (cansee(x,y)) prl(x,y);
  271.                 break;
  272.             }
  273.         }
  274. }
  275.  
  276. /*
  277.  * The player is trying to extract something from his/her instrument.
  278.  */
  279.  
  280. static int
  281. do_improvisation(instr)
  282. struct obj *instr;
  283. {
  284.     int damage;
  285.  
  286.     if (Confusion)
  287.       pline("What you produce is quite far from music...");
  288.     else
  289.       You("start playing the %s.", xname(instr));
  290.     switch (instr->otyp) {
  291.           case FLUTE:    /* May charm snakes */
  292.         if (rn2(ACURR(A_DEX)) + u.ulevel > 25)
  293.           charm_snakes((int)u.ulevel*3);
  294.         break;
  295.           case MAGIC_FLUTE: /* Make monster fall asleep */
  296.         if (instr->spe > 0) {
  297.             instr->spe--;
  298.             You("produce soft music.");
  299.             put_monsters_to_sleep((int)u.ulevel*5);
  300.         }
  301.         break;
  302.           case HORN:    /* Awaken monsters or scare monsters */
  303.         You("produce a frightful, grave sound.");
  304.         awaken_monsters((int)u.ulevel*30);
  305.         break;
  306.           case FROST_HORN:    /* Idem wand of cold */
  307.           case FIRE_HORN:    /* Idem wand of fire */
  308.         if (instr->spe > 0) {
  309.             instr->spe--;
  310.             if (!getdir(1)) {
  311.                 if (!Blind)
  312.                     pline("The %s glows then fades.", xname(instr));
  313.             } else {
  314.                 if (!u.dx && !u.dy && !u.dz) {
  315.                     if((damage = zapyourself(instr)))
  316.                       losehp(damage,
  317.         self_pronoun("using a magical horn on %sself", "him"),
  318.                       NO_KILLER_PREFIX);
  319.                     makeknown(instr->otyp);
  320.                     return(2);
  321.                 }
  322.                 buzz((instr->otyp == FROST_HORN) ? 3 : 1, rn1(6,6), u.ux, u.uy, u.dx, u.dy);
  323.                 makeknown(instr->otyp);
  324.                 return(2);
  325.             }
  326.         }
  327.         break;
  328.           case BUGLE:    /* Awaken & attract soldiers */
  329.         You("extract a loud noise from the %s.",xname(instr));
  330.         awaken_soldiers();
  331.         break;
  332.           case HARP:    /* May calm Nymph */
  333.         if (rn2(ACURR(A_DEX)) + u.ulevel > 25)
  334.           calm_nymphs((int)u.ulevel*3);
  335.         break;
  336.           case MAGIC_HARP:    /* Charm monsters */
  337.         if (instr->spe > 0) {
  338.             pline("The %s produces very attractive music.", xname(instr));
  339.             instr->spe--;
  340.             charm_monsters(((int)u.ulevel - 1) / 3 + 1);
  341.         }
  342.         break;
  343.           case DRUM:    /* Awaken monsters */
  344.         You("beat a deafening row!");
  345.         awaken_monsters((int)u.ulevel * 40);
  346.         break;
  347.           case DRUM_OF_EARTHQUAKE:    /* create several pits */
  348.         if (instr->spe > 0) {
  349.             You("produce a heavy, thunderous rolling!");
  350.             pline("The entire dungeon is shaking around you!");
  351.             instr->spe--;
  352.             do_earthquake(((int)u.ulevel - 1) / 3 + 1);
  353.             makeknown(DRUM_OF_EARTHQUAKE);
  354.         }
  355.         break;
  356.           default:
  357.         impossible("What a weird instrument (%d)!",instr->otyp);
  358.         break;
  359.     }
  360.     return (2);        /* That takes time */
  361. }
  362.  
  363. /*
  364.  * So you want music...
  365.  */
  366.  
  367. int
  368. do_play_instrument(instr)
  369. struct obj *instr;
  370. {
  371. #ifdef STRONGHOLD
  372.     char buf[BUFSZ], *s, c = 'y';
  373.     int x,y;
  374.     boolean ok;
  375.  
  376.     if (instr->otyp != DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) {
  377.     pline("Improvise? ");
  378.     c = yn();
  379.     }
  380.     if (c == 'n') {
  381.     pline("What tune are you playing? [what 5 notes] ");
  382.     getlin(buf);
  383.     for(s=buf;*s;s++)
  384.         if (islower(*s)) *s=toupper(*s);
  385.     You("extract a strange sound from the %s!",xname(instr));
  386.     /* Check if there was the Stronghold drawbridge near
  387.      * and if the tune conforms to what we're waiting for.
  388.      */
  389.     if (dlevel == stronghold_level)
  390.         if (!strcmp(buf,tune)) {
  391.         /* Search for the drawbridge */
  392.         for(y=u.uy-1; y<=u.uy+1; y++)
  393.             for(x=u.ux-1;x<=u.ux+1;x++)
  394.             if(isok(x,y))
  395.             if (find_drawbridge(&x,&y)) {
  396.                 if (levl[x][y].typ == DRAWBRIDGE_DOWN)
  397.                 close_drawbridge(x,y);
  398.                 else
  399.                 open_drawbridge(x,y);
  400.                 return 0;
  401.             }
  402.         } else if (flags.soundok) {
  403.         /* Okay, it wasn't the right tune, but perhaps
  404.          * we can give the player some hints like in the
  405.          * Mastermind game */
  406.         ok = FALSE;
  407.         for(y = u.uy-1; y <= u.uy+1 && !ok; y++)
  408.             for(x = u.ux-1; x <= u.ux+1 && !ok; x++)
  409.             if(isok(x,y))
  410.             if(IS_DRAWBRIDGE(levl[x][y].typ) ||
  411.                is_drawbridge_wall(x,y) >= 0)
  412.                 ok = TRUE;
  413.         if (ok) { /* There is a drawbridge near */
  414.             int tumblers, gears;
  415.             boolean matched[5];
  416.  
  417.             tumblers = gears = 0;
  418.             for(x=0; x < 5; x++)
  419.             matched[x] = FALSE;
  420.  
  421.             for(x=0; x < strlen(buf); x++)
  422.             if(x < 5) {
  423.                 if(buf[x] == tune[x]) {
  424.                 gears++;
  425.                 matched[x] = TRUE;
  426.                 } else
  427.                 for(y=0; y < 5; y++)
  428.                     if(!matched[y] &&
  429.                        buf[x] == tune[y] &&
  430.                        buf[y] != tune[y]) {
  431.                     tumblers++;
  432.                     matched[y] = TRUE;
  433.                     break;
  434.                     }
  435.             }
  436.             if(tumblers)
  437.             if(gears)
  438.                 You("hear %d tumbler%s click and %d gear%s turn.",
  439.                 tumblers, plur((long)tumblers),
  440.                 gears, plur((long)gears));
  441.             else
  442.                 You("hear %d tumbler%s click.",
  443.                 tumblers, plur((long)tumblers));
  444.             else if(gears)
  445.             You("hear %d gear%s turn.",
  446.                 gears, plur((long)gears));
  447.         }
  448.         }
  449.     return 1;
  450.     } else
  451. #endif /* STRONGHOLD /**/
  452.         return do_improvisation(instr);
  453. }
  454.  
  455. #endif /* MUSIC /**/
  456.